package com.novel.captcha.autoConfiguration;

import com.novel.captcha.adapter.Captcha;
import com.novel.captcha.adapter.impl.*;
import com.novel.captcha.cache.config.CaptchaCacheProperties;
import com.novel.captcha.cache.impl.RedisCaptchaCache;
import com.novel.captcha.cache.impl.SessionCaptchaCache;
import com.novel.captcha.cache.manager.CaptchaCacheManager;
import com.novel.captcha.cache.manager.RedisCaptchaCacheManagerImpl;
import com.novel.captcha.cache.manager.SessionCaptchaCacheManagerImpl;
import com.novel.captcha.config.CaptchaProperties;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * 验证码配置
 *
 * @author novel
 * @since 2023/8/3 17:30
 */
@Configuration
@EnableConfigurationProperties(CaptchaProperties.class)
public class CaptchaAutoConfiguration {

    /**
     * 验证码缓存注入
     */
    @EnableConfigurationProperties(CaptchaCacheProperties.class)
    @Configuration
    static class CaptchaCacheAutoConfiguration {

        /**
         * 默认使用session缓存
         */
        @ConditionalOnProperty(prefix = CaptchaCacheProperties.PREFIX, name = "type", havingValue = "session", matchIfMissing = true)
        @Configuration
        static class SessionCaptchaCacheManagerAutoConfiguration {

            @Bean
            public SessionCaptchaCache sessionCaptchaCache(CaptchaCacheProperties captchaCacheProperties) {
                return new SessionCaptchaCache(captchaCacheProperties);
            }

            @Primary
            @Bean
            public CaptchaCacheManager captchaCacheManager(SessionCaptchaCache sessionCaptchaCache) {
                return new SessionCaptchaCacheManagerImpl(sessionCaptchaCache);
            }
        }

        /**
         * redis 缓存注入
         */
        @ConditionalOnProperty(prefix = CaptchaCacheProperties.PREFIX, name = "type", havingValue = "redis")
        @Configuration
        @AutoConfigureAfter(StringRedisTemplate.class)
        static class RedisCaptchaCacheManagerAutoConfiguration {
            @Bean
            public RedisCaptchaCache redisCaptchaCache(StringRedisTemplate redisTemplate, CaptchaCacheProperties captchaCacheProperties) {
                return new RedisCaptchaCache(redisTemplate, captchaCacheProperties);
            }

            @Primary
            @Bean
            public CaptchaCacheManager captchaCacheManager(RedisCaptchaCache redisCaptchaCache) {
                return new RedisCaptchaCacheManagerImpl(redisCaptchaCache);
            }
        }
    }


    @Configuration
    @ConditionalOnClass(SpecCaptchaImpl.class)
    @AutoConfigureAfter(CaptchaCacheManager.class)
    static class SpecCaptchaImplAutoConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public Captcha specCaptchaImpl(CaptchaProperties properties, CaptchaCacheManager captchaCacheManager) {
            return switch (properties.getCaptchaType()) {
                case PNG -> new SpecCaptchaImpl(captchaCacheManager, properties);
                case GIF -> new GifCaptchaImpl(captchaCacheManager, properties);
                case CHINESE_PNG -> new ChineseCaptchaImpl(captchaCacheManager, properties);
                case CHINESE_GIF -> new ChineseGifCaptchaImpl(captchaCacheManager, properties);
                case ARITHMETIC_PNG -> new ArithmeticCaptchaImpl(captchaCacheManager, properties);
                default -> throw new IllegalStateException("Unexpected value: " + properties.getCaptchaType());
            };
        }
    }
}
